home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
amok_lha
/
amok71.lha
/
TurboFilesV2.1
/
TurboFiles.mod
< prev
next >
Wrap
Text File
|
1993-08-15
|
11KB
|
407 lines
(**********************************************************************
:Program. (Turbo)Files
:Contents. Module for filehandling, like FileSystem
:Author. Stefan Salewski
:Address. Stefan Salewski, Stolper Weg 3, D-2160 Stade
:Copyright. FD
:Language. Oberon/68000-Assembler
:Translator. Amiga-Oberon-Compiler V2.14 and A68k
:History. V2.0 12-06-91 (on Amok#56)
:History. V2.1 23.02.92 some changes for Oberon V2.14
:Remark. The modules Files and TurboFiles does the same, but
:Remark. TurboFiles is quicker, because the important
:Remark. Procedures are coded in Assembler.
:Remark. Link from CLI: OLink MyProgram OBJ TurboFiles.o
:Remark. or use JOIN to merge TurboFiles.obj(s) and TurboFiles.o
:Remark. The assemblerpart and documentation is on Amok#56
**********************************************************************)
(* Changes for Oberon V2.14d:
Define a new datatype: "TYPE Address=LONGINT"
and replace "Exec.ADDRESS" with "Address"
Replace in the procedure Open() "VAR buf:Address"
with "VAR buf:SYSTEM.ADDRESS"
Replace in the procedure Open() "f.top:=buf+bufferSize;"
with "f.top:=SYSTEM.VAL(LONGINT,buf)+bufferSize;"
In the procedure Close() insert "VAR h:SYSTEM.ADDRESS" and replace
"OberonLib.Dispose(f.base);"
with "h:=f.base; OberonLib.Dispose(h);"
In the procedure Code() replace
"CopyMem(SYSTEM.ADR(code),SYSTEM.ADR(code)+cWLen,cWLen);" with
"CopyMem(SYSTEM.ADR(code),SYSTEM.VAL(LONGINT,SYSTEM.ADR(code))+cWLen,cWLen);"
Replace "VAR DosBase:Address" with "VAR DosBase:SYSTEM.ADDRESS"
*)
MODULE TurboFiles;
IMPORT SYSTEM,
OberonLib,
Dos,
SecureDos,
Exec,
Random,
ASCII,
Strings;
CONST
D0= 0; D1= 1;
A0= 8; A1= 9;
CONST
newFile* = TRUE; (* open new file (delete old one) for read/write *)
oldFile* = FALSE; (* open existing file for read/write *)
CONST (* Error-Codes = file.res *)
done* = 0;
notdone* = 1;
notOpen* = 2;
openError* = 3;
readError* = 4;
writeError* = 5;
seekError* = 6;
endOfFile* = 7;
outOfMem* = 8;
notExists* = 9;
CONST (* Modes for SetPos *)
beginning* = Dos.beginning;
current* = Dos.current;
end* = Dos.end;
TYPE
Address=LONGINT;
File* = RECORD
fhPtr:Dos.FileHandlePtr;
dosBase:Address;
base:Address;
top:Address;
filePos:LONGINT;
startLength:LONGINT;
act:Address;
readTop:Address;
writeBase:Address;
writeTop:Address;
open:BOOLEAN;
res*:SHORTINT;
END;
VAR
DosBase:SYSTEM.ADDRESS;
ExecBase[4]:Address;
PROCEDURE CopyMem{ExecBase,-624}(source{8}:Address;
dest{9}:Address;
size{0}:LONGINT);
PROCEDURE DosRead{DosBase,-42}(file{1}:Dos.FileHandlePtr;
buffer{2}:Address;
length{3}:LONGINT):LONGINT;
PROCEDURE DosWrite{DosBase,-48}(file{1}:Dos.FileHandlePtr;
buffer{2}:Address;
length{3}:LONGINT):LONGINT;
PROCEDURE DeleteFile*{DosBase,-72}(name{1}:ARRAY OF CHAR):BOOLEAN;
PROCEDURE ReadChar*{"TurboReadChar"}
(VAR f{A0}:File;VAR c{A1}:BYTE):BOOLEAN;
PROCEDURE ReadBytes*{"TurboReadBytes"}
(VAR f{A0}:File;adr{A1}:Address;
len{D1}:LONGINT):LONGINT;
PROCEDURE Read*{"TurboRead"}
(VAR f:File;VAR to:ARRAY OF BYTE):BOOLEAN;
PROCEDURE WriteChar*{"TurboWriteChar"}
(VAR f{A0}:File;c{D1}:BYTE):BOOLEAN;
PROCEDURE WriteBytes*{"TurboWriteBytes"}
(VAR f{A0}:File;adr{A1}:Address;
len{D1}:LONGINT):BOOLEAN;
PROCEDURE Write*{"TurboWrite"}
(VAR f:File;from:ARRAY OF BYTE):BOOLEAN;
PROCEDURE Size*{"TurboSize"}
(VAR f{A0}:File):LONGINT;
PROCEDURE GetPos*{"TurboGetPos"}
(VAR f{A0}:File):LONGINT;
PROCEDURE SetPos*{"TurboSetPos"}
(VAR f{A0}:File;offset{D0}:LONGINT;
mode{D1}:LONGINT):BOOLEAN;
PROCEDURE MinLongInt(i,j:LONGINT):LONGINT;
BEGIN
IF i<j THEN RETURN i ELSE RETURN j END;
END MinLongInt;
PROCEDURE Exists*(name: ARRAY OF CHAR;VAR size:LONGINT):BOOLEAN;
(* $CopyArrays- *)
VAR
flPtr:Dos.FileLockPtr;
(* info:Dos.FileInfoBlock; must be on a 4 byte boundary !!! *)
infoPtr:Dos.FileInfoBlockPtr;
exists:BOOLEAN;
BEGIN
exists:=FALSE;
size:=0;
flPtr:=SecureDos.Lock(name,Dos.sharedLock);
IF flPtr#NIL THEN
NEW(infoPtr);
IF infoPtr#NIL THEN
IF Dos.Examine(flPtr,infoPtr^) THEN
exists:=TRUE;
IF infoPtr.dirEntryType<0 THEN (* is a file *)
size:=infoPtr.size;
ELSE
size:=-1 (* is a directory *)
END;
END;
DISPOSE(infoPtr);
END;
SecureDos.UnLock(flPtr);
END;
RETURN exists
END Exists;
PROCEDURE Open*(VAR f:File;name:ARRAY OF CHAR;
bufferSize:LONGINT;new:BOOLEAN):BOOLEAN;
(* $CopyArrays- *)
VAR
buf:SYSTEM.ADDRESS;
mode:LONGINT;
BEGIN
f.open:=FALSE;
IF new THEN
f.startLength:=0;
mode:=Dos.newFile
ELSE
mode:=Dos.oldFile;
IF NOT Exists(name,f.startLength) OR (f.startLength<0) THEN
f.res:=notExists;
RETURN FALSE
END;
END;
IF bufferSize<1 THEN bufferSize:=1 END;
OberonLib.New(buf,bufferSize);
IF buf=NIL THEN
f.res:=outOfMem;
RETURN FALSE
END;
f.fhPtr:=SecureDos.Open(name,mode);
IF f.fhPtr=NIL THEN
OberonLib.Dispose(buf);
f.res:=openError;
RETURN FALSE
ELSE
f.dosBase:=DosBase;
f.filePos:=0;
f.base:=buf;
f.top:=SYSTEM.VAL(LONGINT,buf)+bufferSize;
f.act:=buf;
f.readTop:=buf;
f.writeTop:=buf;
f.writeBase:=f.top;
f.open:=TRUE;
f.res:=done;
RETURN TRUE;
END;
END Open;
PROCEDURE Close*(VAR f:File):BOOLEAN;
VAR h:SYSTEM.ADDRESS;
BEGIN
IF (NOT f.open) OR (f.res=notOpen) THEN RETURN FALSE END;
IF f.writeTop>f.writeBase THEN
IF Dos.Seek(f.fhPtr,f.writeBase-f.readTop,Dos.current) > 0 THEN END;
IF DosWrite(f.fhPtr,f.writeBase,f.writeTop-f.writeBase)> 0 THEN END;
END;
SecureDos.Close(f.fhPtr);
h:=f.base;
OberonLib.Dispose(h);
f.open:=FALSE;
f.res:=notOpen;
RETURN TRUE;
END Close;
PROCEDURE ReadString*(VAR f:File;VAR str:ARRAY OF CHAR):INTEGER;
VAR i:INTEGER;
BEGIN
i:=-1;
LOOP
INC(i);
IF i=LEN(str) THEN EXIT END;
IF NOT ReadChar(f,str[i]) THEN EXIT END;
IF (str[i]=ASCII.nul) OR (str[i]=ASCII.eol) THEN EXIT END;
END;
IF i<LEN(str) THEN str[i]:=0X END;
RETURN i
END ReadString;
PROCEDURE WriteString*(VAR f:File;str:ARRAY OF CHAR):BOOLEAN;
(* CopyArrays- *)
VAR i:INTEGER;
BEGIN
i:=0;
WHILE (i<LEN(str)) AND (str[i]#0X) DO
IF WriteChar(f,str[i]) THEN END;
INC(i);
END;
RETURN f.res=done;
END WriteString;
PROCEDURE WriteLn*(VAR f:File):BOOLEAN;
BEGIN
RETURN WriteChar(f,ASCII.lf);
END WriteLn;
PROCEDURE Search*(VAR f:File;str:ARRAY OF BYTE;len:INTEGER):LONGINT;
(* $CopyArrays- *)
VAR
i:INTEGER;
b:BYTE;
BEGIN
IF NOT (f.open) OR (f.res#done) THEN RETURN -1 END;
IF (len>LEN(str)) OR (len<=0) THEN
len:=LEN(str)
END;
DEC(len);
LOOP
i:=0;
LOOP
IF NOT ReadChar(f,b) THEN RETURN -1 END;
IF (b#str[i]) OR (i=len) THEN
EXIT
END;
INC(i);
END;
IF (str[i]=b) AND SetPos(f,-i-1,current) THEN
RETURN GetPos(f)
ELSIF (i>0) THEN
IF SetPos(f,-i,current) THEN END;
END;
END;
END Search;
PROCEDURE Code*(fileName,codeWord:ARRAY OF CHAR;decode:BOOLEAN):BOOLEAN;
(* $CopyArrays- *)
CONST
Mult=2;
CodeStringSize=127;
BufferSize=1024;
TYPE
CodeString=ARRAY CodeStringSize OF SHORTINT;
VAR
act,i:LONGINT;
cWLen:LONGINT;
f:File;
eof:BOOLEAN;
code,readPuffer,writePuffer,index:CodeString;
PROCEDURE Permute(VAR index,code:CodeString;len:SHORTINT);
VAR
qsum:LONGINT;
i,h,rnd:SHORTINT;
BEGIN
(* generating a permutation of the numbers 0..(len-1).
This permutation depends on code and will be
stored in index
*)
qsum:=0;
i:=0;
WHILE i<len DO
INC(qsum,code[i]);
index[i]:=i;
INC(i);
END;
Random.PutSeed(qsum);
i:=0;
WHILE i<len DO
rnd:=SHORT(Random.RND(len));
h:=index[i];
index[i]:=index[rnd];
index[rnd]:=h;
INC(i);
END;
END Permute;
BEGIN
cWLen:=MinLongInt(Strings.Length(codeWord),CodeStringSize);
CopyMem(SYSTEM.ADR(codeWord),SYSTEM.ADR(code),cWLen);
IF cWLen<=0 THEN
RETURN FALSE
END;
IF Open(f,fileName,BufferSize,oldFile) THEN
WHILE cWLen < (CodeStringSize DIV 2) DO
CopyMem(SYSTEM.ADR(code),SYSTEM.VAL(LONGINT,SYSTEM.ADR(code))+cWLen,cWLen);
INC(cWLen,cWLen);
END;
Permute(index,code,SHORT(SHORT(cWLen)));
i:=0;
WHILE i<cWLen DO
(* $OvflChk- *)
code[i]:=code[i]*Mult;
(* $OvflChk= *)
INC(i);
END;
eof:=FALSE;
WHILE NOT eof DO
act:=ReadBytes(f,SYSTEM.ADR(readPuffer),cWLen);
IF act<cWLen THEN
eof:=TRUE;
f.res:=done; (* So I can write to the file again *)
Permute(index,code,SHORT(SHORT(act)))
END;
IF NOT decode THEN
i:=0;
WHILE i<act DO
(* $OvflChk- *)
INC(readPuffer[i],code[i]);
(* $OvflChk= *)
INC(i);
END;
i:=0;
WHILE i<act DO
writePuffer[i]:=readPuffer[index[i]];
INC(i);
END;
ELSE
i:=0;
WHILE i<act DO
writePuffer[index[i]]:=readPuffer[i];
INC(i);
END;
i:=0;
WHILE i<act DO
(* $OvflChk- *)
DEC(writePuffer[i],code[i]);
(* $OvflChk= *)
INC(i);
END;
END;
IF SetPos(f,-act,current) THEN END;
IF WriteBytes(f,SYSTEM.ADR(writePuffer),act) THEN END;
END;
IF Close(f) THEN END;
RETURN TRUE
ELSE
RETURN FALSE
END;
END Code;
BEGIN
DosBase:=Dos.dos;
IF DosBase=NIL THEN HALT(0) END;
END TurboFiles.